package com.pwt.utils;

import com.pwt.model.crustallus.BoxModel;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author dw
 * @version 1.0.0
 * @date 2021/11/8
 */
public class BoxUtils {

    public static BoxModel getBoxPlots(List<Double> param){
        if(param == null || param.size() < 4) return null;
            // 转成BigDecimal类型，避免失去精度
            BigDecimal[] datas = new BigDecimal[param.size()];
            for(int i=0; i<param.size(); i++){
            datas[i] = BigDecimal.valueOf(param.get(i));
            }
            int len = datas.length;// 数组长度
            Arrays.sort(datas);    // 数组排序，从小到大
            BigDecimal q1 = null;  // 第一四分位
            BigDecimal q2 = null;  // 第二四分位
            BigDecimal q3 = null;  // 第三四分位
            BigDecimal index = null; // 记录下标
            // n代表项数，因为下标是从0开始所以这里理解为：len = n+1
            index = new BigDecimal(len+1).divide(new BigDecimal("4"));
            q1 = getComputeValue(index,datas);
            q2 = getComputeValue(index.multiply(new BigDecimal("2")),datas);
            index = index.multiply(new BigDecimal("3"));
            q3 = getComputeValue(index,datas);

            BoxModel boxModel = new BoxModel();
            if(q1 != null){
                boxModel.setQ1(q1);
            }
            if(q2 != null){
                boxModel.setQ2(q2);
            }
            if(q3 != null){
                boxModel.setQ3(q3);
            }
            BigDecimal iqr = q3.subtract(q1);
            boxModel.setMax(q3.add(iqr.multiply(new BigDecimal("1.5"))));
            boxModel.setMin(q1.subtract(iqr.multiply(new BigDecimal("1.5"))));
            boxModel.setMax(boxModel.getMax().doubleValue() > 0.00 ? boxModel.getMax() : new BigDecimal("0.00"));
            boxModel.setMin(boxModel.getMin().doubleValue() > 0.00 ? boxModel.getMin() : new BigDecimal("0.00"));
            List<BigDecimal> exception = new ArrayList<>();
            for(BigDecimal d : datas){
                if(d.doubleValue() > boxModel.getMin().doubleValue() || d.doubleValue() < boxModel.getMin().doubleValue()){
                    exception.add(d);
                }
            }
            boxModel.setException(exception.toArray(new BigDecimal[exception.size()]));
            return boxModel;
    }

    public static BigDecimal getComputeValue(BigDecimal q1,BigDecimal[] data){
        if(Math.floor(q1.doubleValue()) == q1.doubleValue()){
            q1 = data[q1.intValue()-1];
        }else{
            String q1Str = String.format("%.2f",q1);
            q1Str = "0"+q1Str.substring(q1Str.indexOf("."),q1Str.length());
            int indexOf  =(int) (Math.floor(q1.doubleValue()));

            q1 = data[indexOf-1].multiply(new BigDecimal(1-Double.parseDouble(q1Str))).add(data[indexOf].multiply(new BigDecimal(Double.parseDouble(q1Str))));
        }
        return q1;
    }
}
